<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    input+input {
      margin-left: 10px;
    }
  </style>
</head>

<body>
  <!-- 准备好一个容器，承载整个react -->
  <div id="root"></div>

  <!-- react核心库 -->
  <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
  <!-- 支持react操作dom -->
  <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
  <!-- 将jsx转为js -->
  <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
  <!-- 对组件标签属性进行限制 -->
  <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>

  <script type="text/babel">
  /*
    经典面试题：
      一、react/vue中key有什么作用？（key的内部原理是什么？）
      二、为什么遍历列表时，key最好不要用index?

      1. 虚拟DOM中key的作用：
        (1). 简单的说：key是虚拟DOM对象的标识，在更新显示时key起着重要的作用。
        (2). 详细的说：当状态的数据发生变化时，react会根据【新数据】生成【新的虚拟DOM】，随后react进行【新虚拟DOM】与【旧虚拟DOM】的diff比较，比较规则如下：
              a. 旧虚拟DOM找到新的虚拟DOM相同的key：
                1. 若虚拟DOM中内容没变，直接使用之前的真实DOM
                2. 若虚拟DOM中内容变了，则生成新的真实DOM，随后替换掉页面中之前的真实DOM
              b. 旧虚拟DOM中未找到与新虚拟DOM相同的key:
                1. 根据数据创建新的真实DOM，随后渲染到页面

      2. 用index作为key可能会引发的问题：
        (1). 若对数据进行操作：逆序添加、逆序删除等破坏顺序操作：
          会产生没有必要的真实DOM更新 ==> 界面没问题，但效率低
        (2). 如果结构中还包含输入类的DOM（如input、textarea等）:
          会产生错误的DOM更新 ==> 界面有问题
        (3). 注意！如果不存在对数据进行逆序添加、逆序删除等破坏顺序的操作，仅用于渲染列表用于展示，使用index作为key是没有问题的

      3. 开发中如何选择key:
        (1). 最好使用每条数据的唯一标识作为key，比如id、手机号、身份证号、学号等唯一值
        (2). 如果确定只是简单的展示数据，用index也是可以的
        
  */
    class School extends React.Component {
      state = {
        student_list : [
          {id: 1, name: '橘子1号'},
          {id: 2, name: '橘子2号'},
          {id: 3, name: '橘子3号'},
          {id: 4, name: '橘子4号'},
          {id: 5, name: '橘子5号'},
          {id: 6, name: '橘子6号'},
          {id: 7, name: '橘子7号'},
          {id: 8, name: '橘子8号'},
          {id: 9, name: '橘子9号'},
        ]
      }
      render() {
        return (
          <div>
            <h2>使用index作为key的遍历</h2>
            <div>
              {this.state.student_list.map( (v, i) => <div className="student" key={i}><span>{v.name}</span><input type="text" placeholder="输入一个值再去加个橘子" style={{'marginLeft': '20px'}}/></div> )}
            </div>
            <input type="button" value="往前面加一个橘子" style={{'marginTop': '20px'}} onClick={this.addOrange}/>
            <h2>===================================</h2>
            <h2>使用id作为key的遍历</h2>
            <div>
              {this.state.student_list.map( (v, i) => <div className="student" key={v.id}><span>{v.name}</span><input type="text" placeholder="输入一个值再去加个橘子" style={{'marginLeft': '20px'}}/></div> )}
            </div>
            <input type="button" value="往前面加一个橘子" style={{'marginTop': '20px'}} onClick={this.addOrange}/>
          </div>
        )
      }

      addOrange = () => {
        const id = this.state.student_list[0].id - 1
        const student_list = this.state.student_list.map(v => ({...v}))
        student_list.unshift({ id: id, name: `橘子${id}号` })
        this.setState({student_list})
      }
    }

    ReactDOM.render(<School/>, document.getElementById('root'))
  </script>
</body>

</html>